/* Pirate Ship Factory
* Will Seeger
* Desc: Will generate a pirate ship ride that will have a simple swing animation.
* 2/20/2011
*/

#include "StdAfx.h"
#include "PirateShipFactory.h"
#include "SgObject.h"
#include "SgColor.h"
#include "SgBox.h"
#include "SgComposite.h"
#include "SgPolygon.h"
#include "SgQuad.h"
#include "SgRegularPolygon.h"
#include "SgRegularCylinder.h"
#include "SgRotateAroundPoint.h"
#include "SgTranslate.h"
#include "SgTransform.h"
#include "SgMesh.h"
#include "graphics/GrVector.h"
#include "SgMaterial.h"
#include "SgSphere.h"
//#include "SgScale.h"
#include "AnimationRotatePirateShip.h"

const double GR_PI = 3.1415926535897932384626433832795;

//! Compute the cross product of two vectors (3D).
inline CGrVector CrossProd(const CGrVector &a, const CGrVector &b)
{
   return CGrVector(a.Y()*b.Z() - a.Z()*b.Y(), a.Z()*b.X() - a.X()*b.Z(), a.X()*b.Y() - a.Y()*b.X(), 0);
}

inline void Normalize(GLdouble *v)
{
    GLdouble len = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
    v[0] /= len;
    v[1] /= len;
    v[2] /= len;
}

CPirateShipFactory::CPirateShipFactory(void)
{
	steel = new CSgTexture(L"steel.bmp");
	wood = new CSgTexture(L"bwood.bmp");
	metal = new CSgTexture(L"metalb.bmp");
	wooden = new CSgTexture(L"swood.bmp");
}

CPirateShipFactory::~CPirateShipFactory(void)
{
}

void CPirateShipFactory::Create(CSgComposite *root)
{
	m_root = root;

	CSgPtr<CSgTranslate> finalTrans = new CSgTranslate(-13,0,-150);
	
	CSgPtr<CSgComposite> beams = new CSgComposite();
	CSgPtr<CSgComposite> stand = new CSgComposite();
	CSgPtr<CSgComposite> ship = new CSgComposite();

	CreateBeams(beams);
	CreateStand(stand);
	CreateShip(ship);

	CSgPtr<CSgTranslate> beamsTrans = new CSgTranslate(-4,0,14);
	beamsTrans->AddChild(beams);

	CSgPtr<CSgTranslate> standTran = new CSgTranslate(8,0,10);
	standTran->AddChild(stand);

	CSgPtr<CSgTranslate> shipTran = new CSgTranslate(0,4,0);
	shipTran->AddChild(ship);

    // Animate the ship to spin randomly
	CSgPtr<CSgRotateAroundPoint> shipSpinAnimate = new CSgRotateAroundPoint();
	shipSpinAnimate->SetNormal(0, 0, 1);
	shipSpinAnimate->SetPoint(12, 21, -10);
	shipSpinAnimate->SetAngle(0);
	shipSpinAnimate->AddChild(shipTran);

	CSgPtr<CAnimationRotatePirateShip> animate = new CAnimationRotatePirateShip();
	animate->SetNode(shipSpinAnimate);

	CSgPtr<CSgComposite> miniShip = new CSgComposite();
	CreateMiniShip(miniShip);
	CSgPtr<CSgTranslate> miniShipTrans = new CSgTranslate(4.5,4.9,5);
	miniShipTrans->AddChild(miniShip);

	// code to put the ship into place
	m_timeline->AddChannel(animate);
	finalTrans->AddChild(beamsTrans);
	finalTrans->AddChild(standTran);
	finalTrans->AddChild(shipSpinAnimate);
	finalTrans->AddChild(miniShipTrans);
	m_root->AddChild(finalTrans); // this function will place everything in its final location*/

	//crows nest
	CSgPtr<CSgComposite> CrNest = new CSgComposite();
	CreateCrowsNest(CrNest);

	//build at the 0 coordinate
	//m_root->AddChild(CrNest);
	
	//m_root->AddChild(miniShipTrans);
	//m_root->AddChild(beamsTrans);
	//m_root->AddChild(standTran);
	//m_root->AddChild(shipSpinAnimate);
	// create the base of the ride (bottom of the cylinder)
	//CSgPolygon *testPolygon = new CSgPolygon();
}


/*
 *        Name: CreateFloor()
 * Description: Creates the floor of the ride, this both spins and raises up
 *  Parameters: parent - the parent scene graph node
 */
void CPirateShipFactory::CreateFloor(CSgComposite *parent)
{
	CSgPtr<CSgMaterial> floorMat = new CSgMaterial();
	floorMat->SetDiffuseColor(.7f, .7f, .7f, 1.f);
	floorMat->SetSpecularColor(.7f, .7f, .7f, 1.f);
	parent->AddChild(floorMat);

	CSgPtr<CSgPolygon> floorBottom = new CSgPolygon();
	
	for (double i = 0; i < 38/2; i++)
	{
		GLdouble start[] = {5*cos(i*2*GR_PI/38+2*GR_PI/(38*2.0)),0.0,5*sin(i*2*GR_PI/38+2*GR_PI/(38*2.0))};
		floorBottom->AddVertex3dv(start);
		floorBottom->AddNormal(CGrVector(0, -1, 0));
		floorBottom->AddTexCoord(CGrVector((cos(i * 2 * GR_PI / 38)/2) + 0.5, (sin(i * 2 * GR_PI / 38)/2) + 0.5, 1));
	}

	CSgPtr<CSgRotateAroundPoint> floorTopRotate = new CSgRotateAroundPoint();
	floorTopRotate->SetAngle(180);
	floorTopRotate->SetNormal(CGrVector(1, 0, 0));
	floorTopRotate->SetPoint(CGrVector(0, 0, 0));
	floorTopRotate->AddChild(floorBottom);

	CSgPtr<CSgTranslate> floorTopTrans = new CSgTranslate(0, 0.5, 0);
	floorTopTrans->AddChild(floorTopRotate);

	floorMat->AddChild(floorTopTrans);
}

void CPirateShipFactory::CreateBeams(CSgComposite *parent)
{
	CSgPtr<CSgComposite> beam = new CSgComposite();
	CSgPtr<CSgComposite> beamR = new CSgComposite();
	CSgPtr<CSgRegularCylinder> post = new CSgRegularCylinder();
	CSgPtr<CSgPolygon> beam1 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam2 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam3 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam4 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam5 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam6 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam7 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam8 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam9 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam10 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam11 = new CSgPolygon();
	CSgPtr<CSgPolygon> beam12 = new CSgPolygon();

	CGrVector a(0.0, 0, 0.0);
    CGrVector b(2.0, 0, 0.0);
    CGrVector c(2.0, 0.0, 2.0);
    CGrVector d(0.0, 0.0, 2.0);
    CGrVector e(13, 18, -9);
	CGrVector h(13, 18, -7);

	CGrVector f(15, 18, -9);
	CGrVector g(15, 18, -7);

	CGrVector i(17, 18, -9);
	CGrVector j(17, 18, -7);

	CGrVector k(28.0, 0, 0.0);
    CGrVector l(30.0, 0, 0.0);
    CGrVector m(30.0, 0.0, 2.0);
    CGrVector n(28.0, 0.0, 2.0);

	//Rendering Left
	beam1->AddVertices(a,b,c,d); //Bot 
	CGrVector n1 = CrossProd( (b-a),(c-a) );
	n1.Normalize3();
	beam1->AddNormal( n1 );

	beam2->AddVertices(d,c,g,h); //Front
	CGrVector n2 = -CrossProd( (d-c),(g-c) );
	n2.Normalize3();
	beam2->AddNormal( n2 );
	beam2->AddTexCoord( CGrVector(0,0) );
	beam2->AddTexCoord( CGrVector(0,1) );
	beam2->AddTexCoord( CGrVector(1,1) );
	beam2->AddTexCoord( CGrVector(1,0) );

	beam3->AddVertices(a,d,h,e); //Left
	CGrVector n3 = CrossProd( (d-a),(h-a) );
	n3.Normalize3();
	beam3->AddNormal(n3 );
	beam3->AddTexCoord( CGrVector(0,0) );
	beam3->AddTexCoord( CGrVector(0,1) );
	beam3->AddTexCoord( CGrVector(1,1) );
	beam3->AddTexCoord( CGrVector(1,0) );

	beam4->AddVertices(g,c,b,f); //Right **
	CGrVector n4 = -CrossProd( (c-b),(f-b));
	n4.Normalize3();
	beam4->AddNormal( n4 );
	beam4->AddTexCoord( CGrVector(0,0) );
	beam4->AddTexCoord( CGrVector(0,1) );
	beam4->AddTexCoord( CGrVector(1,1) );
	beam4->AddTexCoord( CGrVector(1,0) );
	
	beam5->AddVertices(b,a,e,f); //Back
	CGrVector n5 = -CrossProd( (b-a),(e-a) );
	n5.Normalize3();
	beam5->AddNormal( n5 );
	beam5->AddTexCoord( CGrVector(0,0) );
	beam5->AddTexCoord( CGrVector(0,1) );
	beam5->AddTexCoord( CGrVector(1,1) );
	beam5->AddTexCoord( CGrVector(1,0) );

	beam6->AddVertices(f,e,h,g); //Top
	CGrVector n6 = CrossProd( (f-e) ,(h-e) );
	n6.Normalize3();
	beam6->AddNormal( n6 );
	beam6->AddTexCoord( CGrVector(0,0) );
	beam6->AddTexCoord( CGrVector(0,1) );
	beam6->AddTexCoord( CGrVector(1,1) );
	beam6->AddTexCoord( CGrVector(1,0) );

	//rendering right
	beam7->AddVertices(k,l,m,n); //Bot 
	beam7->AddNormal( CGrVector(0,-1,0) );

	beam8->AddVertices(j,g,n,m); //Front
	CGrVector n8 = -CrossProd( (j-g),(n-g) );
	n8.Normalize3();
	beam8->AddNormal( n8 );
	beam8->AddTexCoord( CGrVector(0,0) );
	beam8->AddTexCoord( CGrVector(0,1) );
	beam8->AddTexCoord( CGrVector(1,1) );
	beam8->AddTexCoord( CGrVector(1,0) );

	beam9->AddVertices(g,f,k,n); //Left
	CGrVector n9 = -CrossProd( (g-f),(k-f) );
	n9.Normalize3();
	beam9->AddNormal(n9 );
	beam9->AddTexCoord( CGrVector(0,0) );
	beam9->AddTexCoord( CGrVector(0,1) );
	beam9->AddTexCoord( CGrVector(1,1) );
	beam9->AddTexCoord( CGrVector(1,0) );

	beam10->AddVertices(m,l,i,j); //Right **
	CGrVector n10 = -CrossProd( (m-l),(i-l));
	n10.Normalize3();
	beam10->AddNormal( n10 );
	beam10->AddTexCoord( CGrVector(0,0) );
	beam10->AddTexCoord( CGrVector(0,1) );
	beam10->AddTexCoord( CGrVector(1,1) );
	beam10->AddTexCoord( CGrVector(1,0) );
	
	beam11->AddVertices(f,i,l,k); //Back
	CGrVector n11 = -CrossProd( (f-i),(l-i) );
	n11.Normalize3();
	beam11->AddNormal( n11 );
	beam11->AddTexCoord( CGrVector(0,0) );
	beam11->AddTexCoord( CGrVector(0,1) );
	beam11->AddTexCoord( CGrVector(1,1) );
	beam11->AddTexCoord( CGrVector(1,0) );

	beam12->AddVertices(i,f,g,j); //Top
	beam12->AddNormal( CGrVector(0,1,0) );
	beam12->AddTexCoord( CGrVector(0,0) );
	beam12->AddTexCoord( CGrVector(0,1) );
	beam12->AddTexCoord( CGrVector(1,1) );
	beam12->AddTexCoord( CGrVector(1,0) );

	beamR->AddChild(beam7);
	beamR->AddChild(beam8);
	beamR->AddChild(beam9);
	beamR->AddChild(beam10);
	beamR->AddChild(beam11);
	beamR->AddChild(beam12);

	CGrVector v3C(1,0,12);
	CGrVector v4C(1,0,0);

	CSgPtr<CSgTranslate> beamTrans = new CSgTranslate(1.0, 2.0, 1.0);
	beam->AddChild(beam1);
	beam->AddChild(beam2);
	beam->AddChild(beam3);
	beam->AddChild(beam4);
	beam->AddChild(beam5);
	beam->AddChild(beam6);
	beam->AddChild(beam7);
	beam->AddChild(beam8);
	beam->AddChild(beam9);
	beam->AddChild(beam10);
	beam->AddChild(beam11);
	beam->AddChild(beam12);
	beamTrans->AddChild(beam);

	post->SetProperties(4,2,3);
	CSgPtr<CSgTranslate> postTrans = new CSgTranslate(2,0,2);
	postTrans->AddChild(post);
	CSgPtr<CSgTranslate> postTrans2 = new CSgTranslate(2+28,0,2);
	postTrans2->AddChild(post);
	CSgPtr<CSgTranslate> postTrans3 = new CSgTranslate(2,0,-20);
	postTrans3->AddChild(post);

	CSgPtr<CSgRotateAroundPoint> beamRot1 = new CSgRotateAroundPoint();
	beamRot1->SetNormal(0,1,0);
	beamRot1->SetAngle(180);
	beamRot1->SetPoint(16,0,-9);
	beamRot1->AddChild(beamTrans);
	CSgPtr<CSgRotateAroundPoint> postRot1 = beamRot1;
	postRot1->AddChild(postTrans);

	CSgPtr<CSgMaterial> gray = new CSgMaterial();
	gray->SetDiffuseColor(1.f, 1.f, 1.f, 1.f);
	gray->SetSpecularColor(1.f, 1.f, 1.f, 1.f);
	
	gray->AddChild(steel);

	CSgPtr<CSgTranslate> b1Trans = new CSgTranslate(14, 20, -11);
	CSgPtr<CSgTranslate> b2Trans = new CSgTranslate(0,0,4);
		//CGrVector f(15, 18, -9);
	CSgPtr<CSgBox> b1 = new CSgBox(4,2,2,steel);
	b1Trans->AddChild(b1);
	b2Trans->AddChild(b1Trans);
	
	steel->AddChild(b1Trans);
	steel->AddChild(b2Trans);

	steel->AddChild(beamTrans);
	steel->AddChild(beamRot1);
	steel->AddChild(postTrans);
	steel->AddChild(postRot1);

	steel->AddChild(postTrans2);
	steel->AddChild(postTrans3);

	parent->AddChild(gray);
}

// new CSgPtr< > use it on all new commands
// Generate main ship to rotate and use
void CPirateShipFactory::CreateShip(CSgComposite *parent)
{
	CSgPtr<CSgRegularCylinder> post = new CSgRegularCylinder();
	post->SetProperties(20,30,.75);
	CSgPtr<CSgRegularCylinder> crowsNest = new CSgRegularCylinder();
	crowsNest->SetProperties(20,3,3);

	CSgPtr<CSgRegularCylinder> swayBar = new CSgRegularCylinder();
	swayBar->SetProperties(30,8,.75);

	CSgPtr<CSgRotateAroundPoint> swayBarRot = new CSgRotateAroundPoint();
	swayBarRot->SetAngle(90);
	swayBarRot->SetNormal(1,0,0);
	swayBarRot->SetPoint(0,0,.375);
	swayBarRot->AddChild(swayBar);

	CSgPtr<CSgTranslate> swayBarTran = new CSgTranslate(12,16.5,.5);
	swayBarTran->AddChild(swayBarRot);

	CSgPtr<CSgTranslate> postTran = new CSgTranslate(12,.5,5);
	postTran->AddChild(post);
	CSgPtr<CSgTranslate> crowsNestTran = new CSgTranslate(12,26,5);
	crowsNestTran->AddChild(crowsNest);

	CSgPtr<CSgComposite> shipFront = new CSgComposite();
	CSgPtr<CSgPolygon> shipF1 = new CSgPolygon();
	CSgPtr<CSgPolygon> shipF2 = new CSgPolygon();
	CSgPtr<CSgPolygon> shipF3 = new CSgPolygon();
	CSgPtr<CSgPolygon> shipFT = new CSgPolygon();
	CSgPtr<CSgPolygon> shipFI = new CSgPolygon();
	CSgPtr<CSgPolygon> shipSides = new CSgPolygon();
	CSgPtr<CSgPolygon> shipSidesIn = new CSgPolygon();
	CSgPtr<CSgPolygon> shipSidesTop = new CSgPolygon();

	CGrVector a(-2,4,-1);
	CGrVector b(-6,4,5);
	CGrVector c(0,0,2);
	CGrVector d(0,0,8);
	CGrVector e(-2,4,11);
	CGrVector f(24,4,11);
	CGrVector g(22,0,8);
	CGrVector h(26,4,4);
	CGrVector i(3,0,22);

	shipF1->AddVertices(b,a,c);
	CGrVector n1 = -CrossProd( b-a,c-a );
	n1.Normalize3();
	shipF1->AddNormal( n1 );

	shipF2->AddVertices(b,c,d);
	CGrVector n2 = -CrossProd( b-a,c-a );
	n2.Normalize3();
	shipF2->AddNormal( n2 );

	shipF3->AddVertices(b,d,e);
	CGrVector n3 = CrossProd( d-e,b-e );
	n3.Normalize3();
	shipF3->AddNormal( n3 );

	shipFT->AddVertices(a,b,e);
	shipFT->AddNormal( CGrVector(0,1,0) );

	shipFI->AddVertices(a,e,d,c);
	shipFI->AddNormal( CGrVector(1,0,0) );
	
	shipF1->AddTexCoord( CGrVector(0,1) );
	shipF1->AddTexCoord( CGrVector(1,1) );
	shipF1->AddTexCoord( CGrVector(1,0) );
	shipF1->AddTexCoord( CGrVector(0,0) );

	shipF2->AddTexCoord( CGrVector(0,0) );
	shipF2->AddTexCoord( CGrVector(0,1) );
	shipF2->AddTexCoord( CGrVector(1,1) );
	shipF2->AddTexCoord( CGrVector(1,0) );

	shipF3->AddTexCoord( CGrVector(1,0) );
	shipF3->AddTexCoord( CGrVector(0,0) );
	shipF3->AddTexCoord( CGrVector(0,1) );
	shipF3->AddTexCoord( CGrVector(1,1) );

	shipFI->AddTexCoord( CGrVector(0,0) );
	shipFI->AddTexCoord( CGrVector(0,1) );
	shipFI->AddTexCoord( CGrVector(1,1) );
	shipFI->AddTexCoord( CGrVector(1,0) );

	shipFT->AddTexCoord( CGrVector(0,0) );
	shipFT->AddTexCoord( CGrVector(0,1) );
	shipFT->AddTexCoord( CGrVector(1,1) );
	shipFT->AddTexCoord( CGrVector(1,0) );

	shipFront->AddChild(shipF1);
	shipFront->AddChild(shipF2);
	shipFront->AddChild(shipF3);
	shipFront->AddChild(shipFT);
	shipFront->AddChild(shipFI);

	shipSides->AddVertices(e,d,g,f);
	CGrVector nS1 = -CrossProd(e-d,g-d);
	nS1.Normalize3();
	shipSides->AddNormal( nS1 );
	shipSides->AddTexCoord( CGrVector(0,0) );
	shipSides->AddTexCoord( CGrVector(0,1) );
	shipSides->AddTexCoord( CGrVector(2,1) );
	shipSides->AddTexCoord( CGrVector(2,0) );

	shipSidesIn->AddVertices(f,g,d,e);
	CGrVector nS2 = CrossProd(e-d,g-d);
	nS2.Normalize3();
	shipSidesIn->AddNormal( nS2 );
	shipSidesIn->AddTexCoord( CGrVector(0,0) );
	shipSidesIn->AddTexCoord( CGrVector(0,1) );
	shipSidesIn->AddTexCoord( CGrVector(2,1) );
	shipSidesIn->AddTexCoord( CGrVector(2,0) );

	CGrVector St1(-2,4,11-.5);
	CGrVector St2(24,4,11-.5);

	shipSidesTop->AddVertices(e,f,St2,St1);
	shipSidesTop->AddNormal( CGrVector(0,1,0) );
	shipSidesTop->AddTexCoord( CGrVector(0,0) );
	shipSidesTop->AddTexCoord( CGrVector(0,1) );
	shipSidesTop->AddTexCoord( CGrVector(2,1) );
	shipSidesTop->AddTexCoord( CGrVector(2,0) );

	CSgPtr<CSgTranslate> shipSidesInTrans = new CSgTranslate(0,0,-.5);
	shipSidesInTrans->AddChild(shipSidesIn);

	CSgPtr<CSgRotateAroundPoint> sideRot = new CSgRotateAroundPoint();
	sideRot->SetAngle(180);
	sideRot->SetNormal(0,1,0);
	sideRot->SetPoint(11,4,5);
	CSgPtr<CSgRotateAroundPoint> frontRot = sideRot;
	
	frontRot->AddChild(shipFront);
	
	sideRot->AddChild(shipSides);
	sideRot->AddChild(shipSidesIn);
	sideRot->AddChild(shipSidesTop);

	CSgPtr<CSgBox> shipBot = new CSgBox(22,.5,6);
	CSgPtr<CSgTranslate> shipBotT = new CSgTranslate(0,0,4.8);
	shipBotT->AddChild(shipBot);

	CSgPtr<CSgMaterial> brown = new CSgMaterial();
	brown->SetDiffuseColor(.51f, .36f, .25f, 1.f);
	brown->SetSpecularColor(.51f, .36f, .25f, 1.f);

	CSgPtr<CSgMaterial> flatMat = new CSgMaterial();
	flatMat->SetDiffuseColor(1.f, 1.f, 1.f, 1.f);
	flatMat->SetSpecularColor(1.f, 1.f, 1.f, 1.f);

	// Generating Ship Seats
	CSgPtr<CSgBox> shipSeat1 = new CSgBox(2,1.5,5);
	CSgPtr<CSgBox> shipSeatBack = new CSgBox(.125,3,5);
	CSgPtr<CSgTranslate> shipSeat1Trans = new CSgTranslate(1.45,.5,5);
	shipSeat1Trans->AddChild(shipSeat1);

	CSgPtr<CSgBox> shipSeatSides = new CSgBox(2,2.25,.125);
	
	CSgPtr<CSgTranslate> shipSeatBackTrans = new CSgTranslate(1.875,0,0);
	shipSeatBackTrans->AddChild(shipSeatBack);
	shipSeat1Trans->AddChild(shipSeatBackTrans);
	
	CSgPtr<CSgRotateAroundPoint> seatRot = new CSgRotateAroundPoint();
	seatRot->SetAngle(180);
	seatRot->SetNormal(0,1,0);
	seatRot->SetPoint(1,0,2.5);
	seatRot->AddChild(shipSeatSides);
	
	CSgPtr<CSgTranslate> shipSeatSidesTrans = new CSgTranslate(0,0,-2.5);
	shipSeatSidesTrans->AddChild(seatRot);
	
	shipSeatSidesTrans->AddChild(shipSeatSides);
	shipSeat1Trans->AddChild(shipSeatSidesTrans);

	CSgPtr<CSgTranslate> shipSeat2Trans = new CSgTranslate(4,0,0);
	shipSeat2Trans->AddChild(shipSeat1Trans);

	CSgPtr<CSgTranslate> shipSeat3Trans = new CSgTranslate(4,0,0);
	shipSeat3Trans->AddChild(shipSeat2Trans);

	CSgPtr<CSgTranslate> shipSeat4Trans = new CSgTranslate(7,0,0);
	shipSeat4Trans->AddChild(shipSeat3Trans);

	CSgPtr<CSgTranslate> shipSeat5Trans = new CSgTranslate(4,0,0);
	shipSeat5Trans->AddChild(shipSeat4Trans);

	CSgPtr<CSgRegularCylinder> metalBar = new CSgRegularCylinder();
	metalBar->SetProperties(12,3,.125);
	CSgPtr<CSgRegularCylinder> metalTopBar = new CSgRegularCylinder();
	metalTopBar->SetProperties(12,4.25,.125);
	CSgPtr<CSgRotateAroundPoint> topBarRot = new CSgRotateAroundPoint();
	topBarRot->SetAngle(90);
	topBarRot->SetNormal(1,0,0);
	topBarRot->SetPoint(0,0,0);
	topBarRot->AddChild(metalTopBar);

	CSgPtr<CSgTranslate> barTrans = new CSgTranslate(.125,.5,3);
	barTrans->AddChild(metalBar);
	CSgPtr<CSgTranslate> barTrans2 = new CSgTranslate(0,0,4.25);
	barTrans2->AddChild(barTrans);
	CSgPtr<CSgTranslate> topBarTrans = new CSgTranslate(.125,3.5,3);
	topBarTrans->AddChild(topBarRot);

	CSgPtr<CSgComposite> bar = new CSgComposite();

	bar->AddChild(barTrans);
	bar->AddChild(barTrans2);
	bar->AddChild(topBarTrans);

	CSgPtr<CSgTranslate> bar2 = new CSgTranslate(4,0,0);
	bar2->AddChild(bar);
	CSgPtr<CSgTranslate> bar3 = new CSgTranslate(4,0,0);
	bar3->AddChild(bar2);
	CSgPtr<CSgTranslate> bar4 = new CSgTranslate(7,0,0);
	bar4->AddChild(bar3);
	CSgPtr<CSgTranslate> bar5 = new CSgTranslate(4,0,0);
	bar5->AddChild(bar4);

	/////
	brown->AddChild(wood);
	brown->AddChild(metal);

	metal->AddChild(bar);
	metal->AddChild(bar2);
	metal->AddChild(bar3);
	metal->AddChild(bar4);
	metal->AddChild(bar5);

	wood->AddChild(shipSeat1Trans);
	wood->AddChild(shipSeat2Trans);
	wood->AddChild(shipSeat3Trans);
	wood->AddChild(shipSeat4Trans);
	wood->AddChild(shipSeat5Trans);

	wood->AddChild(shipSides);
	wood->AddChild(shipSidesInTrans);
	wood->AddChild(shipSidesTop);
	wood->AddChild(sideRot);

	wood->AddChild(shipFront);
	wood->AddChild(frontRot);

	wood->AddChild(shipBotT);

	wood->AddChild(postTran);
	wood->AddChild(crowsNestTran);
	wood->AddChild(swayBarTran);

	parent->AddChild(brown);
}

void CPirateShipFactory::CreateStand(CSgComposite *parent)
{
	//Stand Generation
	CSgPtr<CSgComposite> stand = new CSgComposite();
	CSgPtr<CSgBox> legS = new CSgBox(1,4,1);
	CSgPtr<CSgTranslate> leg1 = new CSgTranslate(0,0,.5);
	leg1->AddChild(legS);
	CSgPtr<CSgTranslate> leg2 = new CSgTranslate(0,0,5);
	CSgPtr<CSgTranslate> leg3 = new CSgTranslate(5,0,5);
	CSgPtr<CSgTranslate> leg4 = new CSgTranslate(5,0,0);

	CSgPtr<CSgBox> top = new CSgBox(6,1,6);
	CSgPtr<CSgTranslate> topTran = new CSgTranslate(0,4,3);
	topTran->AddChild(top);
	
	leg2->AddChild(leg1);
	leg3->AddChild(leg1);
	leg4->AddChild(leg1);

	//Steps Generation
	CSgPtr<CSgBox> Step1 = new CSgBox(2,1,1);
	CSgPtr<CSgBox> Step2 = new CSgBox(2,2,1);
	CSgPtr<CSgBox> Step3 = new CSgBox(2,3,1);
	CSgPtr<CSgBox> Step4 = new CSgBox(2,4,1);
	CSgPtr<CSgTranslate> Step1T = new CSgTranslate(1,0,9.5);
	CSgPtr<CSgTranslate> Step2T = new CSgTranslate(1,0,8.5);
	CSgPtr<CSgTranslate> Step3T = new CSgTranslate(1,0,7.5);
	CSgPtr<CSgTranslate> Step4T = new CSgTranslate(1,0,6.5);
	Step1T->AddChild(Step1);
	Step2T->AddChild(Step2);
	Step3T->AddChild(Step3);
	Step4T->AddChild(Step4);

	CSgPtr<CSgComposite> steps = new CSgComposite();
	steps->AddChild(Step1T);
	steps->AddChild(Step2T);
	steps->AddChild(Step3T);
	//steps->AddChild(Step4T);

	CSgPtr<CSgMaterial> brown = new CSgMaterial();
	brown->SetDiffuseColor(.51f, .36f, .25f, 1.f);
	brown->SetSpecularColor(.51f, .36f, .25f, 1.f);

	CSgPtr<CSgTexture> wood = new CSgTexture(L"bwood.bmp");
	brown->AddChild(wood);

	stand->AddChild(brown);
	wood->AddChild(leg1);
	wood->AddChild(leg2);
	wood->AddChild(leg3);
	wood->AddChild(leg4);
	wood->AddChild(topTran);

	wood->AddChild(steps);
	wood->AddChild(Step4T);

	CSgPtr<CSgTranslate> stepsTop = new CSgTranslate(3,5,-5.5);
	stepsTop->AddChild(steps);

	wood->AddChild(stepsTop);
	
	parent->AddChild(stand);
}

void CPirateShipFactory::CreateCrowsNest(CSgComposite * parent)
{
	double(*p)[4] = new double[36][4];
	double(*q)[4] = new double[36][4];
	double radium=5;
	for(int i=0; i<36; i++)
	{
		double a = 5.*i*2.*GR_PI/360.;
		p[i][0]=q[i][0]=radium*cos(a);
		p[i][1]=q[i][1]=radium*sin(a);
		p[i][2]=0;
		q[i][2]=3;
		p[i][3]=q[i][3]=1.;
	}

	CSgPtr<CSgMesh> m_mesh = new CSgMesh();
	for(int i=0; i<36; i++)
	{
		
		m_mesh->AddVertex(CGrVector(p[i][0],p[i][1],p[i][2]));
		m_mesh->AddVertex(CGrVector(q[i][0],q[i][1],q[i][2]));
	}

	for(int k=0; k<68; k++)
	{
		GLdouble normal[] = {(p[k][0]+p[k+1][0])/2,(p[k][1]+p[k+1][1])/2,0.};
		Normalize(normal);
		m_mesh->AddNormal(normal);
		if(k%2==0)
		m_mesh->AddFlatQuad(k,k+2,k+3,k+1,k);
	}
	parent->AddChild(m_mesh);
}

void CPirateShipFactory::CreateMiniShip(CSgComposite * parent)
{
	CSgPtr<CSgMesh> shipBelly  = new CSgMesh();

	double wid = 14;        // 20 units wide
    double dep = 10;        // 20 units deep
    int nW = 15;            // Number of quads across
    int nD = 15;            // Number of quads deep

    // Create the vertices and -temporary- normals
    // Note that the surface is nW+1 by nD+1 vertices
    for(int j=0;  j<=nD;  j++)
    {
        for(int i=0;  i<=nW;  i++)
        {
			GLdouble a[] = {1, 0, 0};
			GLdouble b[] = {0, 0, -1};
			GLdouble c[] = {-1, 0, 0};
			GLdouble d[] = {0, 0, 1};
			GLdouble e[] = {0, 1, 0};
			GLdouble f[] = {0, -1, 0};

            double x = (double(i)/double(nW) *  wid - wid/2);
            double z = double(j)/double(nD) * dep - dep/2;
            double y = -5*sin( double(j)/double(nD) * GR_PI);

            shipBelly->AddVertex( CGrVector(x, y, z, 1));
			shipBelly->AddNormal( CGrVector(0, -1, 0, 0));
        }
    }

    // Create the quadrilaterals
    for(int j=0;  j<nD;  j++)
    {
        for(int i=0;  i<nW;  i++)
        {
            int a = j * (nW + 1) + i;
            int b = a + nW + 1;
            int c = b + 1;
            int d = a + 1;

			shipBelly->AddTexCoord(CGrVector(d,c,b,a));
			shipBelly->AddQuad(d,c,b,a);
        }
    }
	shipBelly->ComputeSmoothNormals();

	CSgPtr<CSgTranslate> bellyTrans = new CSgTranslate(12,5,5);
	CSgPtr<CSgRotateAroundPoint> bellyRot = new CSgRotateAroundPoint();
	bellyRot->SetNormal(0, 1, 0);
	bellyRot->SetPoint(0, 0, 0);
	bellyRot->SetAngle(180);
	bellyRot->AddChild(shipBelly);
	bellyTrans->AddChild(shipBelly);
	
	CSgPtr<CSgSphere> shipProw = new CSgSphere(5, true);
	CSgPtr<CSgTranslate> shipProwTrans = new CSgTranslate(5,5,5);
	shipProwTrans->AddChild(shipProw);

	CSgPtr<CSgComposite> miniShipF = new CSgComposite();
	CreateFloor(miniShipF);
	CSgPtr<CSgTranslate> miniShipFTrans = new CSgTranslate(5,4.5,5);
	CSgPtr<CSgRotateAroundPoint> shipFR = new CSgRotateAroundPoint();
	shipFR->SetNormal(0, 1, 0);
	shipFR->SetPoint(0, 0, 0);
	shipFR->SetAngle(90);
	miniShipFTrans->AddChild(shipFR);
	shipFR->AddChild(miniShipF);
	CSgPtr<CSgBox> miniShipMid = new CSgBox(14,.1,10);
	CSgPtr<CSgTranslate> miniShipMidTrans = new CSgTranslate(4.5,4.9,5);
	miniShipMidTrans->AddChild(miniShipMid);

	CSgPtr<CSgMaterial> brown = new CSgMaterial();
	brown->SetDiffuseColor(1.0f, 1.0f, 1.0f, 1.f);
	brown->SetSpecularColor(1.0f, 1.0f, 1.0f, 1.f);

	brown->AddChild(miniShipMidTrans);
	brown->AddChild(miniShipFTrans);
	brown->AddChild(shipProwTrans);
	brown->AddChild(bellyTrans);
		
	CSgPtr<CSgTranslate> brownTrans = new CSgTranslate(-25,-4,16);
	
	CSgPtr<CSgRotateAroundPoint> brownRot = new CSgRotateAroundPoint();
	brownRot->SetNormal(0, 0, 1);
	brownRot->SetPoint(10, 4, 6);
	brownRot->SetAngle(-60);
	brownRot->AddChild(brown);

	brownTrans->AddChild(brownRot);

	wooden->AddChild(brownTrans);
	parent->AddChild(wooden);

}
